readonly SELF_NAME=${0}
readonly SCRIPT_PATH=`realpath $(dirname $0)`
readonly COMMON_CFG="${SCRIPT_PATH}/common.sh"
source "${COMMON_CFG}"
readonly TESTSUITE_SRC_PATH=${WORK_PATH}/llvm-test-suite
readonly REPORT_PATH=${SCRIPT_PATH}/Report
readonly TESTSUITE_BUILD_PATH=${TESTSUITE_SRC_PATH}/build
#TODO
readonly LLVM_LIT_PATH=${WORK_PATH}/Tools/lit
readonly TEST_DATA=${REPORT_PATH}/result.txt
readonly CHECK_TESTSUITE_SOURCE_CODE_DATA=${REPORT_PATH}/check_testsuite_source_code_log
TOOLCHAIN_PATH="/srv/work_dir/workspace/llvm-testsuite/test/toolchain/clang-dev"
SYSROOT="/srv/work_dir/workspace/llvm-testsuite/test/toolchain/sysroot"
TRUPLE="aarch64-unkonwn-linux-ohos"
#TODO
CFLAGS="-fuse-ld=lld"
JOBS="${NPROC}"
PREPARE_ONLY=0
TIMEOUT=7200
RESULT=-1
UPDATE_FLAG=1
ACTION=run
CFLAGS_C="--target=${TRUPLE} --sysroot=${SYSROOT} -O0"
CFLAGS_CXX="-std=c++14"
PLATFORM="linux"
UNTESTLIST="${SCRIPT_PATH}/config/LLVM_TestSuite_untestlist"

#TODO
export PATH=/srv/work_dir/workspace/llvm-daily/master/prebuilts/cmake/linux-x86/bin:$PATH

source "${COMMON_CFG}"

function check_env()
{
    rm -rf ${REPORT_PATH} && mkdir -p ${REPORT_PATH}/run_log

    # Check testsuite source code
    # git_clone_or_update "${UPDATE_FLAG}" "${TESTSUITE_SRC_LINK}" "${TESTSUITE_SRC_PATH}" "${TESTSUITE_SRC_BRANCH}"

    rm -rf ${TESTSUITE_BUILD_PATH} && mkdir ${TESTSUITE_BUILD_PATH}

    # Check the toolchain
    if [ -d ${TOOLCHAIN_PATH} ]; then
        CC=${TOOLCHAIN_PATH}/bin/clang
        ${CC} -v >& ${REPORT_PATH}/version.txt
        VERSION=`cat ${REPORT_PATH}/version.txt | sed -n '/clang version/p'`
        echo -e "##### Toolchain : ${VERSION} #####\n"
        echo -e "##### CFLAGS : ${CFLAGS} #####\n"
        echo -e "##### CFLAGS_C : ${CFLAGS_C} #####\n"
        echo -e "##### CFLAGS_CXX : ${CFLAGS_CXX} #####\n"
    else
        echo -e "ERROR : Toolchain is not found!\n"
        print_toolchain_path "${TOOLCHAIN_PATH}"
        exit 1
    fi

    # set lit env
    export PATH=${LLVM_LIT_PATH}:$PATH

    # get skip cases
    [ -f ${UNTESTLIST}.cfail ] && CMP_SKIP="=$(cat ${UNTESTLIST}.cfail)="
    [ -f ${UNTESTLIST}.rfail ] && RUN_SKIP="=$(cat ${UNTESTLIST}.rfail)="
    CMP_SKIP=`echo ${CMP_SKIP} | sed 's/ /=/g'`
    RUN_SKIP=`echo ${RUN_SKIP} | sed 's/ /=/g'`
}


function init_testsuite()
{
    local build_log=${REPORT_PATH}/build.log

    # build tools
    local build_tools=${TESTSUITE_SRC_PATH}/build_tools
    rm -rf ${build_tools} && mkdir ${build_tools} && cd ${build_tools}
    cmake -DCMAKE_C_COMPILER=gcc -DTEST_SUITE_COLLECT_CODE_SIZE=OFF -C ../cmake/caches/O3.cmake ../ | tee ${build_log}
    check_result $? "Cmake tools"
    make build-timeit fpcmp-target build-fpcmp build-HashProgramOutput.sh timeit-target | tee -a ${build_log}
    check_result $? "Build tools"

    # Cmake testsuite
    cd ${TESTSUITE_BUILD_PATH}
    cp ${SCRIPT_PATH}/config/default.cmake ${TESTSUITE_SRC_PATH}/cmake/caches/
    cmake -DCMAKE_C_COMPILER=${CC} -DCMAKE_CXX_COMPILER=${CC}++ -DCMAKE_C_FLAGS="${CFLAGS} ${CFLAGS_C}" -DCMAKE_CXX_FLAGS="${CFLAGS} ${CFLAGS_CXX}" -DTEST_SUITE_RUN_UNDER="${QEMU}" -C ../cmake/caches/default.cmake ../ | tee -a ${build_log}
    check_result $? "Cmake testsuite"

    # 将构建好的tools拷贝回testsuite构建目录
    rm -rf ${TESTSUITE_BUILD_PATH}/tools
    cp -rf ${build_tools}/tools ${TESTSUITE_BUILD_PATH}

    cd ${TESTSUITE_BUILD_PATH}
    make build-litsupport | tee -a ${build_log}
    check_result $? "build build-litsupport"
}

function run_testlist()
{
    test_list=${SCRIPT_PATH}/config/linux_testlist
    cat ${test_list} | grep ^[^#] > ${REPORT_PATH}/testlist

    [ ${PREPARE_ONLY} -eq 1 ] && return

    rm -rf tmp
    mkfifo tmp
    exec 9<>tmp
    rm -rf tmp

    for ((i=0;i<${JOBS};i++))
    do
        echo "" >&9
    done

    while read line
    do {
        read -u 9
        {
            local case_path=`echo "$line" | awk '{print $1}'`
            local case_name=`echo "$line" | awk '{print $2}'`
            run_case ${case_path} ${case_name}
            echo "" >&9
        }&
        echo "$line"
    } done < ${test_list}
    wait
    exec 9>&-
    exec 9<&-
}

function run_case()
{
    local case_relative_path=$1
    local case_name=$2
    local log_file=${REPORT_PATH}/run_log/${case_name}.log
    local lit_test=${case_name}.test

    if [[ ${case_relative_path} == *MicroBenchmarks* || ${case_relative_path} == *Bitcode* ]]; then
        # 若是MicroBenchmarks相关用例，新建build路径，隔离用例间的编译依赖
        local case_build_path=${TESTSUITE_SRC_PATH}/test_${case_name}
        local case_path=${case_build_path}/${case_relative_path}

        # Cmake testsuite
        rm -rf ${case_build_path} && mkdir -p ${case_build_path}
        cd ${case_build_path} || exit 1
        cmake -DCMAKE_C_COMPILER=${CC} -DCMAKE_CXX_COMPILER=${CC}++ -DCMAKE_C_FLAGS="${CFLAGS} ${CFLAGS_C}" -DCMAKE_CXX_FLAGS="${CFLAGS} ${CFLAGS_CXX}" -DTEST_SUITE_RUN_UNDER="${QEMU}" -C ../cmake/caches/default.cmake ../ | tee ${log_file}
        check_result $? "Cmake testsuite" ${log_file}

        # 将构建好的tools拷贝回testsuite构建目录
        rm -rf ${case_build_path}/tools
        cp -rf ${TESTSUITE_SRC_PATH}/build_tools/tools ${case_build_path}
        cd ${case_build_path} || exit 1
        make build-litsupport | tee -a ${log_file}
        check_result $? "build build-litsupport" ${log_file}
    else
        local case_path=${TESTSUITE_BUILD_PATH}/${case_relative_path}
    fi

    cd ${case_path}
    [ -n "$(echo "${CMP_SKIP}" | grep "=${case_name}=")" ] && return 0

    # build case
    echo -e "Start building case:\n" | tee ${log_file}
    timeout ${TIMEOUT} make ${case_name} VERBOSE=1 | tee -a ${log_file}
    local result=$?
    if [ ${result} -ne 0 ]; then
        echo "${case_name} ---- CFAIL" >> ${TEST_DATA}
        if [ ${result} -eq 124 ]; then
            echo -e "\n  ---- build case timeout!!!" | tee -a ${log_file}
        fi
        return 1
    fi

    if [ "${ACTION}" == "build" ] || [ ! -f ${lit_test} ] \
        || [ -n "$(echo "${RUN_SKIP}" | grep "=${case_name}=")" ]; then
        echo "${case_name} ---- PASS(Compile Only)" >> ${TEST_DATA}
        rm -rf ${log_file}
        if [[ -d ${case_build_path} ]];then
            rm -rf ${case_build_path}
        fi
        return 0
    fi

    # run case
    echo -e "\n\nStart running case:\n" | tee -a ${log_file}
    timeout ${TIMEOUT} lit.py -v -j 1 ${lit_test} | tee -a ${log_file}
    local result=$?
    if [ ${result} -ne 0 ]; then
        echo "${case_name} ---- RFAIL" >> ${TEST_DATA}
        if [ ${result} -eq 124 ]; then
            echo -e "\n  ---- run case timeout!!!" | tee -a ${log_file}
        fi
        return 2
    fi

    echo "${case_name} ---- PASS" >> ${TEST_DATA}
    rm -rf ${log_file}
    if [[ -d ${case_build_path} ]];then
         rm -rf ${case_build_path}
    fi
    return 0
}

function get_report()
{
    if [ ${PREPARE_ONLY} -eq 1 ]; then
        RESULT=0
        return 0
    fi
    if [ ! -f ${TEST_DATA} ]; then
        RESULT=-1
        return 1
    fi

    local summary_file=${REPORT_PATH}/summary.txt
    local PASS=`cat ${TEST_DATA} | grep " PASS" | wc -l`
    local CFAIL=`cat ${TEST_DATA} | grep " CFAIL$" | wc -l`
    local RFAIL=`cat ${TEST_DATA} | grep " RFAIL$" | wc -l`
    local TOTAL=`expr ${PASS} + ${CFAIL} + ${RFAIL}`
    local result_str="\
============================= FINAL  RESULT =============================
   Total ${TOTAL}   Passed ${PASS}   Compile Failed ${CFAIL} \
  Execute Failed ${RFAIL}
========================================================================="
    echo -e "\n${result_str}\n"
    echo -e "${result_str}\n" > ${summary_file}
    local CFAIL_LIST=`cat ${TEST_DATA} | grep CFAIL$`
    local RFAIL_LIST=`cat ${TEST_DATA} | grep RFAIL$`
    echo "${CFAIL_LIST}" >> ${summary_file}
    echo "${RFAIL_LIST}" >> ${summary_file}

    RESULT=`expr ${CFAIL} + ${RFAIL}`
    #${RESULT_SCRIPT} ${REPORT_PATH} ${TOTAL} ${PASS} ${RESULT}
    if [ ${RESULT} -eq 0 ]; then
        echo -e "Perfect, all test cases passed.\n"
    else
        echo -e "Oops, some test cases failed, please check!\n"
        RESULT=1
    fi

    echo -e "Detailed reports are in the directory [${REPORT_PATH}]\n"
}

function main()
{
    #get_opts "$@"

    echo -e "\n********** LLVM Testsuite test starting $(date) **********\n\n"

    # check environment
    check_env

    #init testsuite
    #init_testsuite

    # run test
    run_testlist

    # report
    get_report

    echo -e "\n********** LLVM Testsuite test finished $(date) **********\n"

    exit ${RESULT}
}

main "$@"
